#include "Game.h"
//http://www.rastertek.com/dx10tut02.html

Game::Game(LPCSTR appName, int resx, int resy, bool fullscreen = false)
{
	m_AppName = appName;
	m_XResolution = resx;
	m_YResolution = resy;
	m_IsFullScreenApp = false;

	m_GraphicsDevice = 0;
}
Game::~Game()
{

}

bool Game::Frame()
{
	if(m_Input->IsKeyDown(VK_ESCAPE))
		return false;

	return m_GraphicsDevice->Frame();
}
void Game::SetupWindows()
{
	WNDCLASSEX wc;
	DEVMODE dmScreenSettings;
	int posx, posy;

	GameHandle = this;

	m_AppHandle = GetModuleHandle(NULL);
	

	wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	wc.lpfnWndProc = WndProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = m_AppHandle;
	wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
	wc.hIconSm = wc.hIcon;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = m_AppName;
	wc.cbSize = sizeof(WNDCLASSEX);

	RegisterClassEx(&wc);

	if(m_IsFullScreenApp)
	{
		m_XResolution = GetSystemMetrics(SM_CXSCREEN);
		m_YResolution = GetSystemMetrics(SM_CYSCREEN);

		memset(&dmScreenSettings, 0, CDS_FULLSCREEN);
		dmScreenSettings.dmSize = sizeof(dmScreenSettings);
		dmScreenSettings.dmPelsWidth = (unsigned long)m_XResolution;
		dmScreenSettings.dmPelsHeight = (unsigned long)m_YResolution;
		dmScreenSettings.dmBitsPerPel = 32;
		dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

		ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
		posx = posy = 0;
	}
	else
	{
		posx = (GetSystemMetrics(SM_CXSCREEN) - m_XResolution) / 2;
		posy = (GetSystemMetrics(SM_CYSCREEN) - m_YResolution) / 2;
	}

	m_hwnd = CreateWindowEx(
		WS_EX_APPWINDOW,
		m_AppName,
		m_AppName,
		WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP,
		posx, posy, m_XResolution, m_YResolution,
		NULL, NULL, m_AppHandle, NULL);


	ShowWindow(m_hwnd, SW_SHOW);
	SetForegroundWindow(m_hwnd);
	SetFocus(m_hwnd);

	return;
}
void Game::ShutdownWindows()
{
	if(m_IsFullScreenApp)
		ChangeDisplaySettings(NULL, 0);

	DestroyWindow(m_hwnd);
	m_hwnd = NULL;

	UnregisterClass(m_AppName, m_AppHandle);
	m_AppHandle = NULL;

	GameHandle = NULL;

	return;
}

bool Game::Initialize()
{
	bool result;
	SetupWindows();

	m_GraphicsDevice = new GraphicsDevice;
	if(!m_GraphicsDevice)
		return false;

	m_Input = new Input;
	if(!m_Input)
		return false;
	
	result = m_GraphicsDevice->Initialize(m_XResolution, m_YResolution, m_hwnd);
	if(!result)
		return false;

	m_Input->Initialize();
	return true;
}
void Game::Run()
{
	MSG msg;
	bool done, result;

	ZeroMemory(&msg, sizeof(MSG));

	done = false;
	while(!done)
	{
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		if(msg.message == WM_QUIT)
			done = true;
		else
		{
			result = Frame();
			if(!result)
				done = true;
		}
	}
}
void Game::Exit()
{
	if(m_GraphicsDevice)
	{
		m_GraphicsDevice->Shutdown();
		delete m_GraphicsDevice;
		m_GraphicsDevice = 0;
	}

	if(m_Input)
	{
		delete m_Input;
		m_Input = 0;
	}

	ShutdownWindows();
	return;
}


LRESULT CALLBACK Game::MessageHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
	switch(msg)
	{
		case WM_KEYDOWN: m_Input->KeyDown((unsigned int)wparam); return 0; 
		case WM_KEYUP: m_Input->KeyUp((unsigned int)wparam); return 0;

		default: break;
	}

	return DefWindowProc(hwnd, msg, wparam, lparam);
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
	switch(msg)
	{
		case WM_DESTROY: 
		case WM_CLOSE:
			PostQuitMessage(0); 
			return 0;

		default: break;
	}

	return GameHandle->MessageHandler(hwnd, msg, wparam, lparam);
}